﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;

namespace StarUtils.Extension
{

    public static class EnumHelper
    {
        public static TEnum Parse<TEnum>(object member)
        {
            string value = member.SafeString();
            if (value.IsEmpty())
            {
                if (typeof(TEnum).IsGenericType)
                {
                    return default(TEnum);
                }

                throw new ArgumentNullException("member");
            }

            return (TEnum)System.Enum.Parse(Common.GetType<TEnum>(), value, ignoreCase: true);
        }

        public static string GetName<TEnum>(object member)
        {
            return GetName(Common.GetType<TEnum>(), member);
        }

        public static string GetName(Type type, object member)
        {
            if (type == null)
            {
                return string.Empty;
            }

            if (member == null)
            {
                return string.Empty;
            }

            if (member is string)
            {
                return member.ToString();
            }

            if (!type.GetTypeInfo().IsEnum)
            {
                return string.Empty;
            }

            return System.Enum.GetName(type, member);
        }

        public static string[] GetNames<TEnum>()
        {
            return GetNames(typeof(TEnum));
        }

        public static string[] GetNames(Type type)
        {
            return System.Enum.GetNames(type);
        }

        public static int GetValue<TEnum>(object member)
        {
            return GetValue(Common.GetType<TEnum>(), member);
        }

        public static int GetValue(Type type, object member)
        {
            if (member.SafeString().IsEmpty())
            {
                throw new ArgumentNullException("member");
            }

            return (int)System.Enum.Parse(type, member.ToString(), ignoreCase: true);
        }

        public static string GetDescription<T>(object member)
        {
            return Reflection.GetDescription<T>(GetName<T>(member));
        }

        public static string GetDescription(Type type, object member)
        {
            return Reflection.GetDescription(type, GetName(type, member));
        }

        public static List<JsonItem> GetItems<TEnum>()
        {
            return GetItems(typeof(TEnum));
        }

        public static List<JsonItem> GetItems(Type type)
        {
            type = Common.GetType(type);
            if (!type.IsEnum)
            {
                throw new InvalidOperationException($"类型 {type} 不是枚举");
            }

            List<JsonItem> list = new List<JsonItem>();
            FieldInfo[] fields = type.GetFields();
            foreach (FieldInfo field in fields)
            {
                AddItem(type, list, field);
            }

            return list.OrderBy((JsonItem t) => t.SortId).ToList();
        }

        private static void ValidateEnum(Type enumType)
        {
            if (!enumType.IsEnum)
            {
                throw new InvalidOperationException($"类型 {enumType} 不是枚举");
            }
        }

        private static void AddItem(Type type, ICollection<JsonItem> result, FieldInfo field)
        {
            if (field.FieldType.IsEnum)
            {
                int value = GetValue(type, field.Name);
                string description = Reflection.GetDescription(field);
                result.Add(new JsonItem(description, value, value));
            }
        }

        public static TEnum GetEnumItemByDescription<TEnum>(string desc)
        {
            if (desc.IsEmpty())
            {
                throw new ArgumentNullException("desc");
            }

            Type typeFromHandle = typeof(TEnum);
            FieldInfo fieldInfo = typeFromHandle.GetFields(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((FieldInfo p) => p.GetCustomAttribute<DescriptionAttribute>(inherit: false)!.Description == desc);
            if (fieldInfo == null)
            {
                throw new ArgumentNullException("在枚举（" + typeFromHandle.FullName + "）中，未发现描述为“" + desc + "”的枚举项。");
            }

            return (TEnum)System.Enum.Parse(typeFromHandle, fieldInfo.Name);
        }

        public static Dictionary<int, string> GetDictionary<TEnum>()
        {
            TypeInfo typeInfo = Common.GetType<TEnum>().GetTypeInfo();
            ValidateEnum(typeInfo);
            Dictionary<int, string> result = new Dictionary<int, string>();
            FieldInfo[] fields = typeInfo.GetFields();
            foreach (FieldInfo field in fields)
            {
                AddItem<TEnum>(result, field);
            }

            return result;
        }

        private static void AddItem<TEnum>(Dictionary<int, string> result, FieldInfo field)
        {
            if (field.FieldType.GetTypeInfo().IsEnum)
            {
                int value = GetValue<TEnum>(field.Name);
                string description = Reflection.GetDescription(field);
                result.Add(value, description);
            }
        }
    }
}
